{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "1f9b866d",
   "metadata": {},
   "source": [
    "# MindSpore NumPy函数"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "db78dbba",
   "metadata": {},
   "source": [
    "[![](https://gitee.com/mindspore/docs/raw/master/resource/_static/logo_source.png)](https://gitee.com/mindspore/docs/blob/master/docs/programming_guide/source_zh_cn/numpy.ipynb)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0aef812f",
   "metadata": {},
   "source": [
    "## 概述\n",
    "MindSpore NumPy工具包提供了一系列类NumPy接口。用户可以使用类NumPy语法在MindSpore上进行模型的搭建。\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b0493f28",
   "metadata": {},
   "source": [
    "> 本样例适用于CPU、GPU和Ascend环境。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "04e894b7",
   "metadata": {},
   "source": [
    "## 算子介绍\n",
    "\n",
    "MindSpore Numpy具有四大功能模块：张量生成、张量操作、逻辑运算和其他常用数学运算。算子的具体相关信息可以参考[NumPy接口列表](https://www.mindspore.cn/doc/api_python/zh-CN/master/mindspore/mindspore.numpy.html)。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f7e8061c",
   "metadata": {},
   "source": [
    "### 张量生成\n",
    "\n",
    "生成类算子用来生成和构建具有指定数值、类型和形状的数组(Tensor)。\n",
    "\n",
    "构建数组代码示例："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "3f91f03d",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "input_x = [1. 2. 3.]\n",
      "type of input_x = Tensor[Float32]\n"
     ]
    }
   ],
   "source": [
    "import mindspore.numpy as np\n",
    "import mindspore.ops as ops\n",
    "input_x = np.array([1, 2, 3], np.float32)\n",
    "print(\"input_x =\", input_x)\n",
    "print(\"type of input_x =\", ops.typeof(input_x))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e427e6dc",
   "metadata": {},
   "source": [
    "除了使用上述方法来创建外，也可以通过以下几种方式创建。\n",
    "\n",
    "#### 生成具有相同元素的数组\n",
    "\n",
    "生成具有相同元素的数组代码示例："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "19a785d8",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[6. 6. 6.]\n",
      " [6. 6. 6.]]\n"
     ]
    }
   ],
   "source": [
    "input_x = np.full((2, 3), 6, np.float32)\n",
    "print(input_x)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "257149b7",
   "metadata": {},
   "source": [
    "生成指定形状的全1数组，示例："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "695f6528",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[1. 1. 1.]\n",
      " [1. 1. 1.]]\n"
     ]
    }
   ],
   "source": [
    "input_x = np.ones((2, 3), np.float32)\n",
    "print(input_x)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "94a547c1",
   "metadata": {},
   "source": [
    "#### 生成具有某个范围内的数值的数组\n",
    "生成指定范围内的等差数组代码示例："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "ba059077",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0 1 2 3 4]\n"
     ]
    }
   ],
   "source": [
    "input_x = np.arange(0, 5, 1)\n",
    "print(input_x)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9cd769be",
   "metadata": {},
   "source": [
    "#### 生成特殊类型的数组\n",
    "\n",
    "生成给定对角线处下方元素为1，上方元素为0的矩阵，示例："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "543d193a",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[1. 1. 0.]\n",
      " [1. 1. 1.]\n",
      " [1. 1. 1.]]\n"
     ]
    }
   ],
   "source": [
    "input_x = np.tri(3, 3, 1)\n",
    "print(input_x)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f2a73ae5",
   "metadata": {},
   "source": [
    "生成对角线为1，其他元素为0的二维矩阵，示例："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "d8684139",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[1. 0.]\n",
      " [0. 1.]]\n"
     ]
    }
   ],
   "source": [
    "input_x = np.eye(2, 2)\n",
    "print(input_x)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d5b00a83",
   "metadata": {},
   "source": [
    "### 张量操作\n",
    "\n",
    "变换类算子主要进行数组的维度变换，分割和拼接等。\n",
    "\n",
    "#### 数组维度变换\n",
    "\n",
    "矩阵转置，代码示例："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "1c52f955",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[0 2 4 6 8]\n",
      " [1 3 5 7 9]]\n"
     ]
    }
   ],
   "source": [
    "input_x = np.arange(10).reshape(5, 2)\n",
    "output = np.transpose(input_x)\n",
    "print(output)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0a6d6a40",
   "metadata": {},
   "source": [
    "交换指定轴，代码示例："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "801a9d2b",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(2, 1, 3)\n"
     ]
    }
   ],
   "source": [
    "input_x = np.ones((1, 2, 3))\n",
    "output = np.swapaxes(input_x, 0, 1)\n",
    "print(output.shape)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ea1112ce",
   "metadata": {},
   "source": [
    "#### 数组分割\n",
    "\n",
    "将输入数组平均切分为多个数组，代码示例："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "9972887e",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(Tensor(shape=[3], dtype=Int32, value= [0, 1, 2]), Tensor(shape=[3], dtype=Int32, value= [3, 4, 5]), Tensor(shape=[3], dtype=Int32, value= [6, 7, 8]))\n"
     ]
    }
   ],
   "source": [
    "input_x = np.arange(9)\n",
    "output = np.split(input_x, 3)\n",
    "print(output)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2ba0295b",
   "metadata": {},
   "source": [
    "#### 数组拼接\n",
    "\n",
    "将两个数组按照指定轴进行拼接，代码示例："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "2dfbb898",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[ 0  1  2  3  4 10 11 12 13 14]\n"
     ]
    }
   ],
   "source": [
    "input_x = np.arange(0, 5)\n",
    "input_y = np.arange(10, 15)\n",
    "output = np.concatenate((input_x, input_y), axis=0)\n",
    "print(output)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b2d3179f",
   "metadata": {},
   "source": [
    "### 逻辑运算\n",
    "\n",
    "逻辑计算类算子主要进行逻辑运算。\n",
    "\n",
    "相等（equal）和小于（less）计算代码示例如下："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "3da450be",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "output of equal: [ True False False False False]\n",
      "output of less: [False  True  True  True  True]\n"
     ]
    }
   ],
   "source": [
    "input_x = np.arange(0, 5)\n",
    "input_y = np.arange(0, 10, 2)\n",
    "output = np.equal(input_x, input_y)\n",
    "print(\"output of equal:\", output)\n",
    "output = np.less(input_x, input_y)\n",
    "print(\"output of less:\", output)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9864a214",
   "metadata": {},
   "source": [
    "### 数学运算\n",
    "\n",
    "数学计算类算子主要进行各类数学计算：\n",
    "加减乘除乘方，以及指数、对数等常见函数等。\n",
    "\n",
    "数学计算支持类似NumPy的广播特性。\n",
    "\n",
    "#### 加法\n",
    "\n",
    "以下代码实现了`input_x`和`input_y`两数组相加的操作："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "43181748",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[4 6]\n",
      " [4 6]\n",
      " [4 6]]\n"
     ]
    }
   ],
   "source": [
    "input_x = np.full((3, 2), [1, 2])\n",
    "input_y = np.full((3, 2), [3, 4])\n",
    "output = np.add(input_x, input_y)\n",
    "print(output)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f4362309",
   "metadata": {},
   "source": [
    "#### 矩阵乘法\n",
    "\n",
    "以下代码实现了`input_x`和`input_y`两矩阵相乘的操作："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "1ae6290e",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[20. 23. 26. 29.]\n",
      " [56. 68. 80. 92.]]\n"
     ]
    }
   ],
   "source": [
    "input_x = np.arange(2*3).reshape(2, 3).astype('float32')\n",
    "input_y = np.arange(3*4).reshape(3, 4).astype('float32')\n",
    "output = np.matmul(input_x, input_y)\n",
    "print(output)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b89083ba",
   "metadata": {},
   "source": [
    "#### 求平均值\n",
    "\n",
    "以下代码实现了求`input_x`所有元素的平均值的操作："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "02758594",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2.5\n"
     ]
    }
   ],
   "source": [
    "input_x = np.arange(6).astype('float32')\n",
    "output = np.mean(input_x)\n",
    "print(output)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a001a6c3",
   "metadata": {},
   "source": [
    "#### 指数\n",
    "\n",
    "以下代码实现了自然常数`e`的`input_x`次方的操作："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "00be7675",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[ 1.         2.7182817  7.389056  20.085537  54.59815  ]\n"
     ]
    }
   ],
   "source": [
    "input_x = np.arange(5).astype('float32')\n",
    "output = np.exp(input_x)\n",
    "print(output)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6839221e",
   "metadata": {},
   "source": [
    "## MindSpore Numpy与MindSpore特性结合\n",
    "\n",
    "`mindspore.numpy`能够充分利用MindSpore的强大功能，实现算子的自动微分，并使用图模式加速运算，帮助用户快速构建高效的模型。同时，MindSpore还支持多种后端设备，包括`Ascend`、`GPU`和`CPU`等，用户可以根据自己的需求灵活设置。以下提供了几种常用方法：\n",
    "\n",
    "- `ms_function`: 将代码包裹进图模式，用于提高代码运行效率。\n",
    "- `GradOperation`: 用于自动求导。\n",
    "- `mindspore.context`: 用于设置运行模式和后端设备等。\n",
    "- `mindspore.nn.Cell`: 用于建立深度学习模型。\n",
    "\n",
    "### ms_function使用示例\n",
    "\n",
    "首先，以神经网络里经常使用到的矩阵乘与矩阵加算子为例："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "8d01fd0b",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[ 768.  768.  768.  768.]\n",
      " [2816. 2816. 2816. 2816.]]\n"
     ]
    }
   ],
   "source": [
    "import mindspore.numpy as np\n",
    "\n",
    "x = np.arange(8).reshape(2, 4).astype('float32')\n",
    "w1 = np.ones((4, 8))\n",
    "b1 = np.zeros((8,))\n",
    "w2 = np.ones((8, 16))\n",
    "b2 = np.zeros((16,))\n",
    "w3 = np.ones((16, 4))\n",
    "b3 = np.zeros((4,))\n",
    "\n",
    "def forward(x, w1, b1, w2, b2, w3, b3):\n",
    "    x = np.dot(x, w1) + b1\n",
    "    x = np.dot(x, w2) + b2\n",
    "    x = np.dot(x, w3) + b3\n",
    "    return x\n",
    "\n",
    "print(forward(x, w1, b1, w2, b2, w3, b3))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ba7143b6",
   "metadata": {},
   "source": [
    "对上述示例，我们可以借助`ms_function`将所有算子编译到一张静态图里以加快运行效率，示例如下："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "0d09df6d",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[ 768.  768.  768.  768.]\n",
      " [2816. 2816. 2816. 2816.]]\n"
     ]
    }
   ],
   "source": [
    "from mindspore import ms_function\n",
    "\n",
    "forward_compiled = ms_function(forward)\n",
    "print(forward(x, w1, b1, w2, b2, w3, b3))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f4d34964",
   "metadata": {},
   "source": [
    "> 目前静态图不支持在命令行模式中运行，并且有部分语法限制。`ms_function`的更多信息可参考[API: ms_function](https://www.mindspore.cn/doc/api_python/zh-CN/master/mindspore/mindspore.html#mindspore.ms_function)。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4d792fe5",
   "metadata": {},
   "source": [
    "### GradOperation使用示例\n",
    "\n",
    "`GradOperation` 可以实现自动求导。以下示例可以实现对上述没有用`ms_function`修饰的`forward`函数定义的计算求导。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "efe84e9a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(Tensor(shape=[2, 4], dtype=Float32, value=\n",
       " [[ 5.12000000e+02,  5.12000000e+02,  5.12000000e+02,  5.12000000e+02],\n",
       "  [ 5.12000000e+02,  5.12000000e+02,  5.12000000e+02,  5.12000000e+02]]),\n",
       " Tensor(shape=[4, 8], dtype=Float32, value=\n",
       " [[ 2.56000000e+02,  2.56000000e+02,  2.56000000e+02 ...  2.56000000e+02,  2.56000000e+02,  2.56000000e+02],\n",
       "  [ 3.84000000e+02,  3.84000000e+02,  3.84000000e+02 ...  3.84000000e+02,  3.84000000e+02,  3.84000000e+02],\n",
       "  [ 5.12000000e+02,  5.12000000e+02,  5.12000000e+02 ...  5.12000000e+02,  5.12000000e+02,  5.12000000e+02]\n",
       "  [ 6.40000000e+02,  6.40000000e+02,  6.40000000e+02 ...  6.40000000e+02,  6.40000000e+02,  6.40000000e+02]]),\n",
       "  ...\n",
       " Tensor(shape=[4], dtype=Float32, value= [ 2.00000000e+00,  2.00000000e+00,  2.00000000e+00,  2.00000000e+00]))"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from mindspore import ops\n",
    "\n",
    "grad_all = ops.composite.GradOperation(get_all=True)\n",
    "grad_all(forward)(x, w1, b1, w2, b2, w3, b3)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4c3af4d4",
   "metadata": {},
   "source": [
    "如果要对`ms_function`修饰的`forward`计算求导，需要提前使用`context`设置运算模式为图模式，示例如下："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "26f0536c",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(Tensor(shape=[2, 4], dtype=Float32, value=\n",
       " [[ 5.12000000e+02,  5.12000000e+02,  5.12000000e+02,  5.12000000e+02],\n",
       "  [ 5.12000000e+02,  5.12000000e+02,  5.12000000e+02,  5.12000000e+02]]),\n",
       " Tensor(shape=[4, 8], dtype=Float32, value=\n",
       " [[ 2.56000000e+02,  2.56000000e+02,  2.56000000e+02 ...  2.56000000e+02,  2.56000000e+02,  2.56000000e+02],\n",
       "  [ 3.84000000e+02,  3.84000000e+02,  3.84000000e+02 ...  3.84000000e+02,  3.84000000e+02,  3.84000000e+02],\n",
       "  [ 5.12000000e+02,  5.12000000e+02,  5.12000000e+02 ...  5.12000000e+02,  5.12000000e+02,  5.12000000e+02]\n",
       "  [ 6.40000000e+02,  6.40000000e+02,  6.40000000e+02 ...  6.40000000e+02,  6.40000000e+02,  6.40000000e+02]]),\n",
       "  ...\n",
       " Tensor(shape=[4], dtype=Float32, value= [ 2.00000000e+00,  2.00000000e+00,  2.00000000e+00,  2.00000000e+00]))"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from mindspore import ms_function, context\n",
    "\n",
    "context.set_context(mode=context.GRAPH_MODE)\n",
    "grad_all = ops.composite.GradOperation(get_all=True)\n",
    "grad_all(ms_function(forward))(x, w1, b1, w2, b2, w3, b3)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e118f560",
   "metadata": {},
   "source": [
    "更多细节可参考[API: GradOperation](https://www.mindspore.cn/doc/api_python/zh-CN/master/mindspore/ops/mindspore.ops.GradOperation.html)。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "82f796a5",
   "metadata": {},
   "source": [
    "### mindspore.context使用示例\n",
    "\n",
    "MindSpore支持多后端运算，可以通过`mindspore.context`进行设置。`mindspore.numpy` 的多数算子可以使用图模式或者PyNative模式运行，也可以运行在CPU，CPU或者Ascend等多种后端设备上。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "86a72556",
   "metadata": {},
   "source": [
    "```python\n",
    "from mindspore import context\n",
    "\n",
    "# Execucation in static graph mode\n",
    "context.set_context(mode=context.GRAPH_MODE)\n",
    "\n",
    "# Execucation in PyNative mode\n",
    "context.set_context(mode=context.PYNATIVE_MODE)\n",
    "\n",
    "# Execucation on CPU backend\n",
    "context.set_context(device_target=\"CPU\")\n",
    "\n",
    "# Execucation on GPU backend\n",
    "context.set_context(device_target=\"GPU\")\n",
    "\n",
    "# Execucation on Ascend backend\n",
    "context.set_context(device_target=\"Ascend\")\n",
    "...\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "310bca4b",
   "metadata": {},
   "source": [
    "更多细节可参考[API: mindspore.context](https://www.mindspore.cn/doc/api_python/zh-CN/master/mindspore/mindspore.context.html)。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d0ae90bd",
   "metadata": {},
   "source": [
    "### mindspore.numpy使用示例\n",
    "\n",
    "这里提供一个使用`mindspore.numpy`构建网络模型的示例。\n",
    "\n",
    "`mindspore.numpy` 接口可以定义在`nn.Cell`代码块内进行网络的构建，示例如下："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "7f43c68b",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[ 768.  768.  768.  768.]\n",
      " [2816. 2816. 2816. 2816.]]\n"
     ]
    }
   ],
   "source": [
    "import mindspore.numpy as np\n",
    "from mindspore import context\n",
    "from mindspore.nn import Cell\n",
    "\n",
    "context.set_context(mode=context.GRAPH_MODE)\n",
    "\n",
    "x = np.arange(8).reshape(2, 4).astype('float32')\n",
    "w1 = np.ones((4, 8))\n",
    "b1 = np.zeros((8,))\n",
    "w2 = np.ones((8, 16))\n",
    "b2 = np.zeros((16,))\n",
    "w3 = np.ones((16, 4))\n",
    "b3 = np.zeros((4,))\n",
    "\n",
    "class NeuralNetwork(Cell):\n",
    "    def __init__(self):\n",
    "        super(NeuralNetwork, self).__init__()\n",
    "\n",
    "    def construct(self, x, w1, b1, w2, b2, w3, b3):\n",
    "        x = np.dot(x, w1) + b1\n",
    "        x = np.dot(x, w2) + b2\n",
    "        x = np.dot(x, w3) + b3\n",
    "        return x\n",
    "\n",
    "net = NeuralNetwork()\n",
    "\n",
    "print(net(x, w1, b1, w2, b2, w3, b3))\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0afb8298",
   "metadata": {},
   "source": [
    "更多构建网络的细节可以参考[MindSpore训练指导](https://www.mindspore.cn/tutorial/training/zh-CN/master/index.html)。"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "MindSpore-1.1.1",
   "language": "python",
   "name": "mindspore-1.1.1"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
